#include <rtthread.h>
#include <rtdevice.h>
#include "./drv_pcf8563.h"

static struct rt_device rtc;

static time_t get_rtc_timestamp(rt_device_t dev);
static rt_err_t set_rtc_time_stamp(rt_device_t dev, time_t time_stamp);
static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args);

time_t get_rtc_timestamp(rt_device_t dev)
{
    struct pcf8563_time value;
    PCF8563_Read_Time(&value);

    struct tm tm_new;

    tm_new.tm_sec = value.second;
    tm_new.tm_min = value.minute;
    tm_new.tm_hour = value.hour;
    tm_new.tm_mday = value.day;
    tm_new.tm_mon = value.month - 1;
    tm_new.tm_year = value.year;

    return mktime(&tm_new);
}

rt_err_t set_rtc_time_stamp(rt_device_t dev, time_t time_stamp)
{
    struct pcf8563_time value;
    struct tm *p_tm;

    p_tm = localtime(&time_stamp);

    value.second = p_tm->tm_sec;
    value.minute = p_tm->tm_min;
    value.hour = p_tm->tm_hour;
    value.day = p_tm->tm_mday;
    value.month = p_tm->tm_mon + 1;
    value.year = p_tm->tm_year;

    PCF8563_Set_Time(&value);

    return RT_EOK;
}

rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
{
    rt_err_t result = RT_EOK;
    RT_ASSERT(dev != RT_NULL);
    switch (cmd)
    {
    case RT_DEVICE_CTRL_RTC_GET_TIME:
        *(rt_uint32_t *)args = get_rtc_timestamp(dev);
        break;

    case RT_DEVICE_CTRL_RTC_SET_TIME:
        if (set_rtc_time_stamp(dev, *(rt_uint32_t *)args))
        {
            result = -RT_ERROR;
        }
        break;
    }

    return result;
}

#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops rtc_ops =
    {
        RT_NULL,
        RT_NULL,
        RT_NULL,
        RT_NULL,
        RT_NULL,
        rt_rtc_control};
#endif

static int stm32_RTC_register(void)
{
    rt_device_t pcf8563 = rt_device_find("pcf8563"); /* 查找硬件RTC设备 */

#ifdef RT_USING_DEVICE_OPS
    rtc.ops = &rtc_ops;
#else

    rtc.init = RT_NULL;
    rtc.open = RT_NULL;
    rtc.close = RT_NULL;
    rtc.read = RT_NULL;
    rtc.write = RT_NULL;
    rtc.control = rt_rtc_control;
#endif
    rtc.type = RT_Device_Class_RTC;
    rtc.rx_indicate = RT_NULL;
    rtc.tx_complete = RT_NULL;
    rtc.user_data = pcf8563;

    /* register a character device */
    return rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
}
INIT_COMPONENT_EXPORT(stm32_RTC_register);
